import './index.css'
import {Button, Drawer, Form, Input, message, Modal, Popconfirm, Radio, Switch, Table, Tree} from "antd"
import {useCallback, useEffect, useState} from "react"
import {useOutletContext} from "react-router-dom"
import {DatabaseOutlined, SearchOutlined} from "@ant-design/icons"
import {
    changeRole,
    createRole,
    deleteRole,
    getAllRole,
    getDefaultRole,
    queryRole,
    setDefaultRole,
    setRoleEnable
} from "../../../request/role"
import {allocateMenuForRole, getAllMenu} from "../../../request/menu"
import {getIcon} from "../../../utils/dynamic-icon"

const columns = [
    {
        title: '默认角色',
        dataIndex: 'default',
        key: 'default',
        align: 'center',
        width: 100
    },
    {
        title: '角色名称',
        dataIndex: 'name',
        key: 'name',
        align: 'center',
        width: 200
    },
    {
        title: '描述',
        dataIndex: 'describe',
        key: 'describe',
        align: 'center',
        width: 300
    },
    {
        title: '用户数',
        dataIndex: 'count',
        key: 'count',
        align: 'center',
        width: 100
    },
    {
        title: '添加时间',
        dataIndex: 'created_at',
        key: 'created_at',
        align: 'center',
        width: 200
    },
    {
        title: '是否启用',
        dataIndex: 'enable',
        key: 'enable',
        align: 'center',
        width: 100
    },
    {
        title: '操作',
        dataIndex: 'operation',
        key: 'operation',
        align: 'center'
    }
]

function Role() {
    const [onMenuChange] = useOutletContext()
    let [data, setData] = useState([])
    let [editing, setEditing] = useState({})
    let [title, setTitle] = useState('')
    let [allocating, setAllocating] = useState({})
    let [checkedKeys, setCheckedKeys] = useState([])
    let [search, setSearch] = useState('')
    let [defaultRoleId, setDefaultRoleId] = useState('')
    const [form] = Form.useForm()

    const getDefaultRoleId = useCallback(() => {
        getDefaultRole().then(setDefaultRoleId).catch(message.error)
    }, [])
    useEffect(getDefaultRoleId, [getDefaultRoleId])

    const loadRoles = useCallback((name = undefined) => {
        function enableRole(item, enable) {
            setRoleEnable(item.name, enable).then(() => {
                onMenuChange()
            }).catch(message.error)
        }

        function doDeleteRole(item) {
            deleteRole(item.name).then(() => {
                onMenuChange()
                loadRoles()
                message.success('删除成功')
            }).catch(message.error)
        }

        function loadRolesInner(data) {
            return data.map(role => {
                role.key = role.id
                role.enable = <Switch defaultChecked={role.enable} onChange={
                    (checked) => enableRole(role, checked)
                }/>
                role.default = (
                    <Radio checked={defaultRoleId === role.id} onChange={e => {
                        if (e.target.checked) {
                            setDefaultRole(role.id).then(() => {
                                getDefaultRoleId()
                            }).catch(message.error)
                        }
                    }}/>
                )
                role.operation = (
                    <>
                        <Button type="link" onClick={() => {
                            let key = 0
                            const checkedKeys = []

                            function loadMenu(items) {
                                if (!items) return undefined
                                return items.filter(item => item.show).map(item => {
                                    const newItem = {
                                        title: <>{getIcon(item.icon)}&nbsp;{item.label}</>,
                                        name: item.name,
                                        children: loadMenu(item.children)
                                    }
                                    newItem.key = ++key
                                    let checked = item.auth.includes(role.id)
                                    if (checked && item.children) {
                                        checked = item.children.filter(i => !i.auth.includes(role.id)).length === 0
                                    }
                                    if (checked) {
                                        checkedKeys.push(newItem.key)
                                    }
                                    return newItem
                                })
                            }

                            getAllMenu().then(menu => {
                                const allocating = {
                                    id: role.id,
                                    name: role.name,
                                    menu: loadMenu(menu)
                                }
                                setAllocating(allocating)
                                setCheckedKeys(checkedKeys)
                            })
                        }}>分配菜单</Button>
                        <Button type="link" onClick={() => {
                            setTitle('编辑角色')
                            setEditing(role)
                            form.setFieldsValue(role)
                        }}>编辑</Button>
                        <Popconfirm
                            title="确认删除"
                            description="你确定要删除该角色吗?"
                            onConfirm={() => {
                                doDeleteRole(role)
                            }}
                            okText="是"
                            cancelText="否"
                        >
                            <Button type="link">删除</Button>
                        </Popconfirm>
                    </>
                )
                return role
            })
        }

        if (name) {
            queryRole(name).then(roles => {
                setData(loadRolesInner(roles))
                message.success(`查询到${roles.length}个角色`)
            }).catch(message.error)
        } else {
            getAllRole(true).then(roles => {
                setData(loadRolesInner(roles))
            }).catch(message.error)
        }
    }, [defaultRoleId, form, getDefaultRoleId, onMenuChange])
    useEffect(loadRoles, [loadRoles])

    function tryEdit({name, describe}) {
        const promise = editing.key !== -1 ?
            changeRole(editing.name, name, describe) : createRole(name, describe)
        promise.then(() => {
            setEditing({})
            onMenuChange()
            loadRoles()
            message.success(editing.key !== -1 ? '修改成功' : '创建成功')
        }).catch(message.error)
    }

    function updateMenu() {
        function getSubmitMenu(items) {
            if (!items) return undefined
            return items.map(item => {
                const submitItem = {
                    name: item.name,
                    children: getSubmitMenu(item.children),
                    permit: checkedKeys.includes(item.key)
                }
                if (!submitItem.permit && submitItem.children) {
                    for (const child of submitItem.children) {
                        if (child.permit) {
                            submitItem.permit = true
                            break
                        }
                    }
                }
                return submitItem
            })
        }

        const submitMenu = getSubmitMenu(allocating.menu)
        allocateMenuForRole(allocating.id, submitMenu)
            .then(() => {
                message.success('更新成功')
                onMenuChange()
            }).catch(message.error)
        setAllocating({})
    }

    return (
        <>
            <div className="content-item-box">
                <div className="search">
                    <div className="label"><SearchOutlined/>筛选搜索</div>
                    <label>
                        <span>输入搜索</span>
                        <Input placeholder="请输入名称" value={search}
                               onChange={e => setSearch(e.target.value)}></Input>
                    </label>
                </div>
                <div className="blank"></div>
                <Button onClick={() => {
                    setSearch('')
                    loadRoles()
                }}>重置</Button>
                <Button type="primary" onClick={() => {
                    loadRoles(search)
                }}>搜索</Button>
            </div>
            <div className="content-item-box">
                <DatabaseOutlined/>
                <span>数据列表</span>
                <div className="blank"></div>
                <Button onClick={() => {
                    setTitle('添加角色')
                    const appendItem = {
                        key: -1,
                        name: undefined,
                        describe: undefined
                    }
                    setEditing(appendItem)
                    form.setFieldsValue(appendItem)
                }}>添加</Button>
            </div>
            <Modal
                title={title}
                open={editing.key}
                //onOk={handleOk}
                onCancel={() => setEditing({})}
                footer={[]}
                width={500}
            >
                <Form
                    className="edit-form"
                    onFinish={tryEdit}
                    form={form}>
                    <Form.Item name="name" label="角色名称" rules={[
                        {
                            required: true,
                            message: '请输入角色名称'
                        }
                    ]}>
                        <Input placeholder="请输入角色名称"/>
                    </Form.Item>
                    <Form.Item name="describe" label="角色描述" rules={[
                        {
                            required: true,
                            message: '请输入描述'
                        }
                    ]}>
                        <Input placeholder="请输入描述"/>
                    </Form.Item>
                    <Form.Item>
                        <Button onClick={() => setEditing({})}>取消</Button>
                        <Button type="primary" htmlType="submit">确定</Button>
                    </Form.Item>
                </Form>
            </Modal>
            <Drawer
                title={`为${allocating.name}分配菜单`}
                open={allocating.id}
                onClose={updateMenu}>
                <Tree
                    checkable
                    autoExpandParent
                    treeData={allocating.menu}
                    checkedKeys={checkedKeys}
                    onCheck={checkedKeysValue => {
                        setCheckedKeys(checkedKeysValue)
                    }}
                />
            </Drawer>
            <Table
                columns={columns}
                dataSource={data}
                pagination={false}
            />
        </>
    )
}

export default Role